package mandel;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;


public class MainFrame extends javax.swing.JFrame {

	private Coordinates coords;
	
	private static PanelDessin panel_Dessin;
	private static Timer timer;
	
	private ColorRamp colorRamp;
	private OptimOption optims;

	
	public MainFrame() {
		initComponents();
		
		tf_NbThread.setText(""+Runtime.getRuntime().availableProcessors());
		
		panel_Dessin = new PanelDessin();
		panel_DessinCadre.add(panel_Dessin, java.awt.BorderLayout.CENTER);
		
		coords = new Coordinates(getTailleAA());
		coords.setView1();
		
		Calculateur.init(this);
		
		colorRamp = new ColorRamp(getTaillePalette());
		colorRamp.fillWithGrays();
//		colorRamp.fillWithGrays_inverted();
//		colorRamp.fillRougeVertJaune();
		colorRamp.fillMultiColor();
		majColorRampWithSliders();
		
		optims = new OptimOption();
	}
	
	private void lanceCalcul() {
		// par défaut, on commence le calcul au centre de l'image
		lanceCalcul(panel_Dessin.getWidth()/2, panel_Dessin.getHeight()/2);
	}
	// xMouse et yMouse sont les coordonnées de la souris dans le panel de dessin
	//  cela permet de commencer le calcul dans cette zone, qui est celle interessant
	//  l'utilisateur
	private void lanceCalcul(int xMouse, int yMouse) {
		if (Calculateur.bIscalculating)
			Calculateur.stopCalcul();
		
		updateInfo();
		btn_Calcul.setEnabled(false);
		btn_STOP.setEnabled(true);
		
		
		// Update éventuelle de la taille AA
		coords.changeTailleAA(getTailleAA());
		// On s'assure que la taille courante du panel de dessin est bien prise en compte
		coords.panelSizeChanged(panel_Dessin.getWidth(), panel_Dessin.getHeight());

		// Si zoom via souris, alors on demande au Calculateur de calculer d'abord
		//  dans la zone de la souris
		double xToDrawFirst = coords.getXFromI_disp(xMouse);
		double yToDrawFirst = coords.getYFromJ_disp(yMouse);
		
		// Calcul éventuellement automatique du nombre d'itérations en fonction du zoom
		// Il faut avoir lu avant la taille de l'AA, car ce calcul du nb d'iter depend notamment
		//  de la taille des pixels calculés ...
		if (cb_AutoNbIter.isSelected()) {
			int nbIterAuto = Calculateur.getNbIterFromZoom(coords.get_zoomLevel(), coords.get_nbPixelLarg_aa());
			tf_NbIter.setText("" + nbIterAuto);
		}
		
		if (getTaillePalette() != colorRamp.getTaillePalette()) {
			colorRamp = new ColorRamp(getTaillePalette());
			majColorRampWithSliders();
			colorRamp.fillMultiColor();
		}
		
		readOptimOptions();
		
		Calculateur.startCalcul(coords, getNbIter(), xToDrawFirst, yToDrawFirst, colorRamp, optims);
		
		if (timer==null) {
			timer = new Timer(500, new ActionListener() {
						@Override
						public void actionPerformed(ActionEvent e) {
							panel_DessinCadre.repaint();
						}
					});
		}
		timer.start();
		
		// Une pré-image est déjà prête en guise d'attente, donc on l'affiche immédiatement
		//  avant le 1er tick du timer
		panel_Dessin.repaint();
	}
	
	// Modifie la colorRamp à partir des paramètres dans l'IHM
	private void majColorRampWithSliders() {
		colorRamp.setDecalageColor((double)slider_Color.getValue()/1000.0);
		colorRamp.setFactorColor((double)slider_Color_fact.getValue()/1000.0 * 2);
	}
	private void readOptimOptions() {
		optims.tailleAA = getTailleAA();
		optims.nbThread = getNbThread();
		optims.bOptimFill = cb_OptimFill.isSelected();
		optims.bOptimInterpol = cb_OptimInterpol.isSelected();
		optims.seuilMaxFill = getSeuilMaxFill();
		optims.seuilMaxInterpol = getSeuilMaxInterpol();
	}
	
	private void updateInfo() {
		tf_coordCenter.setText("X : " + coords.get_xCenterView() + "  Y : " + coords.get_yCenterView());
		tf_zoom.setText("" + coords.get_zoomLevel());
	}
	
	private int getTailleAA() {return getIntFromTextField(tf_TailleAA, 1, 1, 3);}
	private int getNbIter() {return getIntFromTextField(tf_NbIter, 1000, 50, 1000000000);}
	private int getNbThread() {return getIntFromTextField(tf_NbThread, 1, 1, 32);}
	private int getSeuilMaxFill() {return getIntFromTextField(tf_SeuilMaxFill, 0, 0, 765);}
	private int getSeuilMaxInterpol() {
		int seuil = getIntFromTextField(tf_SeuilMaxInterpol, 15, 0, 765);
		// le seuil interpol ne peut etre inferieur au seuil fill
		if (seuil<getSeuilMaxFill()) {
			seuil = getSeuilMaxFill();
			tf_SeuilMaxInterpol.setText(""+seuil);
		}
		return seuil;
	}
	private int getTaillePalette() {return getIntFromTextField(tf_TaillePalette, 1000, 10, 10000);}

	private int getIntFromTextField(JTextField tf, int defaultVal, int min, int max) {
		assert(defaultVal>=min && defaultVal<=max);
		int value = defaultVal;
		try {value = Integer.parseInt(tf.getText());	} catch(Exception ex) {}
		if (value<min) value=min;
		if (value>max) value=max;
		tf.setText(""+value);
		return value;
	}
	
	// Appelé par le calculateur en fin de calcul
	void calculTermine() {
		btn_Calcul.setEnabled(true);
		btn_STOP.setEnabled(false);
		panel_Dessin.repaint();
	}

	//**************************************************************************
	// PANEL DE DESSIN
	//**************************************************************************
	
	public class PanelDessin extends JPanel {
		private BufferedImage img = null;
		
		public PanelDessin() {
			super();
			addComponentListener(new java.awt.event.ComponentAdapter() {
				@Override
				public void componentResized(java.awt.event.ComponentEvent evt) {
					panel_DessinComponentResized(evt);
				}
			});
			addMouseListener(new java.awt.event.MouseAdapter() {
				@Override
				public void mouseClicked(java.awt.event.MouseEvent evt) {
					panel_DessinMouseClicked_(evt);
				}
			});
			addMouseWheelListener(new java.awt.event.MouseWheelListener() {
				@Override
				public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) {
					panel_DessinMouseWheelMoved(evt);
				}
			});
			addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
				@Override
				public void mouseMoved(java.awt.event.MouseEvent evt) {
					panel_DessinMouseMoved(evt);
				}
			});
		}
		
	    private void panel_DessinMouseClicked_(java.awt.event.MouseEvent evt) {
			double xInvariant = coords.getXFromI_disp(evt.getX());
			double yInvariant = coords.getYFromJ_disp(evt.getY());
			
			double zoomLevel_new;
			if (evt.getButton() == MouseEvent.BUTTON1)
				zoomLevel_new = coords.get_zoomLevel() * 2;
			else
				zoomLevel_new = coords.get_zoomLevel() / 2;
			
			coords.zoomWithPointInvariant(xInvariant, yInvariant, zoomLevel_new);
			lanceCalcul(evt.getX(), evt.getY());
		}
		private void panel_DessinMouseWheelMoved(java.awt.event.MouseWheelEvent evt) {                                     
			double xInvariant = coords.getXFromI_disp(evt.getX());
			double yInvariant = coords.getYFromJ_disp(evt.getY());
			
			int nbScroll = evt.getWheelRotation();
			double zoomLevel_new = coords.get_zoomLevel();
			if (nbScroll>0) {
				for (int i = 0; i < nbScroll; i++)
					zoomLevel_new /= 1.5;
			} else {
				for (int i = 0; i < -nbScroll; i++)
					zoomLevel_new *= 1.5;
			}

			coords.zoomWithPointInvariant(xInvariant, yInvariant, zoomLevel_new);
			lanceCalcul(evt.getX(), evt.getY());
		}        
		
		private void panel_DessinComponentResized(java.awt.event.ComponentEvent evt) {
			//coords.panelSizeChanged(); //appelé par lanceCalcul();
			lanceCalcul();
		}
		
		private void panel_DessinMouseMoved(java.awt.event.MouseEvent evt) {
		}
		
		@Override
		protected void paintComponent(Graphics g) {
			//Graphics2D g2d = (Graphics2D)g;
			
			// Le calcul est-il terminé ?
			boolean bDernierPaint_withTimer = !Calculateur.bIscalculating;
			
			long debCalcul, finCalcul;
			debCalcul = System.nanoTime();
			// creation d'une image pour le dessin (recreation que si taille panel a changé
			if (img == null || img.getWidth()!=panel_Dessin.getWidth() || img.getHeight()!=panel_Dessin.getHeight()) {
				//System.out.println("Create Buffered Image");
				img = new BufferedImage(panel_Dessin.getWidth(), panel_Dessin.getHeight(), BufferedImage.TYPE_INT_RGB);
			}
			Calculateur.fillImageWithCurrentData(img, toggle_ShowOptim.isSelected());

			g.drawImage(img, 0, 0, null);
			
			finCalcul = System.nanoTime();
			Logger.log("PAINT : " + ( (double)(finCalcul-debCalcul) / 1000000.0) + " ms ----");
			
			// Si le calcul est terminé, on stoppe le timer et l'image dessinée est bien l'image finale
			if (bDernierPaint_withTimer && timer!=null) {
				timer.stop();
				timer = null;
			}
		}
	}

	@SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        panel_DessinCadre = new javax.swing.JPanel();
        jLabel3 = new javax.swing.JLabel();
        tf_coordCenter = new javax.swing.JTextField();
        jLabel4 = new javax.swing.JLabel();
        tf_zoom = new javax.swing.JTextField();
        jPanel1 = new javax.swing.JPanel();
        btn_Calcul = new javax.swing.JButton();
        btn_STOP = new javax.swing.JButton();
        btn_ReinitView = new javax.swing.JButton();
        pb_Calcul = new javax.swing.JProgressBar();
        jLabel1 = new javax.swing.JLabel();
        tf_NbIter = new javax.swing.JTextField();
        cb_AutoNbIter = new javax.swing.JCheckBox();
        jPanel2 = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        tf_TailleAA = new javax.swing.JTextField();
        jLabel5 = new javax.swing.JLabel();
        tf_NbThread = new javax.swing.JTextField();
        jLabel9 = new javax.swing.JLabel();
        jLabel10 = new javax.swing.JLabel();
        tf_SeuilMaxFill = new javax.swing.JTextField();
        tf_SeuilMaxInterpol = new javax.swing.JTextField();
        toggle_ShowOptim = new javax.swing.JToggleButton();
        cb_OptimFill = new javax.swing.JCheckBox();
        cb_OptimInterpol = new javax.swing.JCheckBox();
        jLabel11 = new javax.swing.JLabel();
        jPanel3 = new javax.swing.JPanel();
        jLabel6 = new javax.swing.JLabel();
        tf_TaillePalette = new javax.swing.JTextField();
        jLabel7 = new javax.swing.JLabel();
        jLabel8 = new javax.swing.JLabel();
        slider_Color = new javax.swing.JSlider();
        slider_Color_fact = new javax.swing.JSlider();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        panel_DessinCadre.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        panel_DessinCadre.setLayout(new java.awt.BorderLayout());

        jLabel3.setText("center : ");

        jLabel4.setText("zoom : ");

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Traitement"));

        btn_Calcul.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        btn_Calcul.setText("GO");
        btn_Calcul.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_CalculActionPerformed(evt);
            }
        });

        btn_STOP.setText("STOP");
        btn_STOP.setEnabled(false);
        btn_STOP.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_STOPActionPerformed(evt);
            }
        });

        btn_ReinitView.setText("Réinit view");
        btn_ReinitView.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_ReinitViewActionPerformed(evt);
            }
        });

        jLabel1.setText("Nb iter :");

        cb_AutoNbIter.setSelected(true);
        cb_AutoNbIter.setText("auto");

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(pb_Calcul, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(btn_Calcul)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btn_STOP)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btn_ReinitView))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(tf_NbIter, javax.swing.GroupLayout.PREFERRED_SIZE, 74, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(cb_AutoNbIter)))
                .addGap(0, 0, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btn_Calcul)
                    .addComponent(btn_STOP)
                    .addComponent(btn_ReinitView))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(tf_NbIter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(cb_AutoNbIter))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 13, Short.MAX_VALUE)
                .addComponent(pb_Calcul, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Optimisation"));

        jLabel2.setText("Antialias :");

        jLabel5.setText("Nb. threads :");

        jLabel9.setText("Seuil max FILL :");

        jLabel10.setText("Seuil max INTERPOL :");

        toggle_ShowOptim.setText("Show optim");
        toggle_ShowOptim.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                toggle_ShowOptimActionPerformed(evt);
            }
        });

        cb_OptimFill.setSelected(true);
        cb_OptimFill.setText("Fill");

        cb_OptimInterpol.setSelected(true);
        cb_OptimInterpol.setText("Interpol");

        jLabel11.setText("Optim rect :");

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addComponent(jLabel2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(tf_TailleAA, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(toggle_ShowOptim)
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel11)
                            .addComponent(jLabel5)
                            .addComponent(cb_OptimFill))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(tf_NbThread, javax.swing.GroupLayout.PREFERRED_SIZE, 31, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addComponent(cb_OptimInterpol)
                        .addGap(12, 12, 12)
                        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addGroup(jPanel2Layout.createSequentialGroup()
                                .addComponent(jLabel9)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(tf_SeuilMaxFill, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(jPanel2Layout.createSequentialGroup()
                                .addComponent(jLabel10)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(tf_SeuilMaxInterpol, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)))))
                .addGap(0, 19, Short.MAX_VALUE))
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(tf_TailleAA, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(tf_NbThread, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel5))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel11)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(cb_OptimFill)
                    .addComponent(jLabel9)
                    .addComponent(tf_SeuilMaxFill, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(cb_OptimInterpol)
                    .addComponent(jLabel10)
                    .addComponent(tf_SeuilMaxInterpol, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(toggle_ShowOptim)
                .addGap(0, 10, Short.MAX_VALUE))
        );

        jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Couleurs"));

        jLabel6.setText("Taille palette :");

        jLabel7.setText("Décal. couleur :");

        jLabel8.setText("Fact. couleur :");

        slider_Color.setMaximum(1000);
        slider_Color.setValue(0);
        slider_Color.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                slider_ColorStateChanged(evt);
            }
        });

        slider_Color_fact.setMaximum(1000);
        slider_Color_fact.setValue(100);
        slider_Color_fact.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                slider_Color_factStateChanged(evt);
            }
        });

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addComponent(jLabel6)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(tf_TaillePalette, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, Short.MAX_VALUE))
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel7)
                    .addComponent(jLabel8, javax.swing.GroupLayout.Alignment.TRAILING))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(slider_Color_fact, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                    .addComponent(slider_Color, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)))
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel6)
                    .addComponent(tf_TaillePalette, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel7)
                    .addComponent(slider_Color, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel8)
                    .addComponent(slider_Color_fact, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(47, 47, 47))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(4, 4, 4)
                        .addComponent(jLabel3)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(tf_coordCenter, javax.swing.GroupLayout.PREFERRED_SIZE, 349, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(16, 16, 16)
                        .addComponent(jLabel4)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(tf_zoom, javax.swing.GroupLayout.DEFAULT_SIZE, 462, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(panel_DessinCadre, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(0, 21, Short.MAX_VALUE))
                    .addComponent(panel_DessinCadre, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(tf_coordCenter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel4)
                    .addComponent(tf_zoom, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btn_CalculActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_CalculActionPerformed
        if (Calculateur.bIscalculating)	return;
		lanceCalcul();
    }//GEN-LAST:event_btn_CalculActionPerformed

    private void slider_ColorStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_slider_ColorStateChanged
        // Pas pendant le calcul, sinon ca peut faire des trucs bizares
		if (Calculateur.bIscalculating) return;
		majColorRampWithSliders();
		Calculateur.changeColorRamp(colorRamp);
		panel_Dessin.repaint();
    }//GEN-LAST:event_slider_ColorStateChanged

    private void btn_ReinitViewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_ReinitViewActionPerformed
        Calculateur.stopCalcul();
		coords = new Coordinates(getTailleAA());
		lanceCalcul();
    }//GEN-LAST:event_btn_ReinitViewActionPerformed

    private void btn_STOPActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_STOPActionPerformed
        Calculateur.stopCalcul();
		panel_Dessin.repaint();
    }//GEN-LAST:event_btn_STOPActionPerformed

    private void slider_Color_factStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_slider_Color_factStateChanged
		// Pas pendant le calcul, sinon ca peut faire des trucs bizares
		if (Calculateur.bIscalculating) return;
		majColorRampWithSliders();
		Calculateur.changeColorRamp(colorRamp);
		panel_Dessin.repaint();
    }//GEN-LAST:event_slider_Color_factStateChanged

    private void toggle_ShowOptimActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_toggle_ShowOptimActionPerformed
        panel_Dessin.repaint();
    }//GEN-LAST:event_toggle_ShowOptimActionPerformed


	public static void main(String args[]) {
		/* Set the Nimbus look and feel */
		//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
		 * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
		 */
		try {
			for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
				if ("Nimbus".equals(info.getName())) {
					javax.swing.UIManager.setLookAndFeel(info.getClassName());
					break;
				}
			}
		} catch (ClassNotFoundException ex) {
			java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
		} catch (InstantiationException ex) {
			java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
		} catch (IllegalAccessException ex) {
			java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
		} catch (javax.swing.UnsupportedLookAndFeelException ex) {
			java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
		}
		//</editor-fold>

		/* Create and display the form */
		java.awt.EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				new MainFrame().setVisible(true);
			}
		});
	}
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btn_Calcul;
    private javax.swing.JButton btn_ReinitView;
    private javax.swing.JButton btn_STOP;
    private javax.swing.JCheckBox cb_AutoNbIter;
    private javax.swing.JCheckBox cb_OptimFill;
    private javax.swing.JCheckBox cb_OptimInterpol;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel panel_DessinCadre;
    private javax.swing.JProgressBar pb_Calcul;
    private javax.swing.JSlider slider_Color;
    private javax.swing.JSlider slider_Color_fact;
    private javax.swing.JTextField tf_NbIter;
    private javax.swing.JTextField tf_NbThread;
    private javax.swing.JTextField tf_SeuilMaxFill;
    private javax.swing.JTextField tf_SeuilMaxInterpol;
    private javax.swing.JTextField tf_TailleAA;
    private javax.swing.JTextField tf_TaillePalette;
    private javax.swing.JTextField tf_coordCenter;
    private javax.swing.JTextField tf_zoom;
    private javax.swing.JToggleButton toggle_ShowOptim;
    // End of variables declaration//GEN-END:variables
}
